#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AGIROS包全量安装测试工具 - 专为openEuler操作系统设计
功能：
1.自动配置eulermaker源，生成agiros包名文件agiros.txt
2.遍历agiros.txt文件中的包名，使用yum命令安装所有包并统计安装结果，将失败包及失败信息写入Excel文件
"""
import os
import sys
import platform
import subprocess
from pathlib import Path


def install_packages_from_file(file_path):
    """
    从文件中读取包名并尝试安装，统计安装结果
    
    Args:
        file_path (str): 包含包名的文件路径
    """
    # 检查是否在支持yum的系统上运行
    if platform.system() != 'Linux' or not os.path.exists('/usr/bin/yum'):
        print("错误：此脚本只能在支持yum的Linux系统（如openEuler）上运行")
        sys.exit(1)
    
    # 检查文件是否存在
    if not os.path.exists(file_path):
        print(f"错误：文件 {file_path} 不存在")
        sys.exit(1)
    
    # 初始化统计变量
    total_count = 0
    success_count = 0
    failed_count = 0
    failed_packages = []
    
    # 读取文件中的包名
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            packages = [line.strip() for line in f if line.strip()]
            
        total_count = len(packages)

        #包如果没有以agiros-loong-开头，就添加
        for i in range(total_count):
            if not packages[i].startswith('agiros-loong-'):
                packages[i] = 'agiros-loong-' + packages[i] 

        print(f"共发现 {total_count} 个包需要安装：")
        print('\n'.join(packages))
        print("\n开始安装过程...\n")
        
        # 用于存储失败包信息的列表
        failed_packages_info = []
        
        # 安装每个包
        for package in packages:
            print(f"安装包：{package}")
            # 在openEuler操作系统下使用yum命令安装包
            result = subprocess.run(
                ['yum', 'install', '-y', package],
                capture_output=True,
                text=True
            )
            
            if result.returncode == 0:
                print(f"  ✓ 安装成功：{package}")
                success_count += 1
            else:
                # 记录安装失败的包及详细信息
                print(f"  ✗ 安装失败：{package}")
                error_msg = result.stderr if result.stderr else "无错误输出"
                print(f"    失败信息：{error_msg}...")
                
                # 保存失败包信息
                failed_packages_info.append({
                    '包名': package,
                    '失败信息': error_msg
                })

                failed_count += 1
                failed_packages.append(package)
        
        # 将失败包信息写入Excel文件
        if failed_packages_info:
            save_failed_packages_to_excel(failed_packages_info)
                
        # 显示统计结果
        print("\n安装统计结果：")
        print(f"总包数：{total_count}")
        print(f"成功安装：{success_count}")
        print(f"安装失败：{failed_count}")
        
        if failed_packages:
            print("\n安装失败的包：")
            print('\n'.join(failed_packages))
            
    except Exception as e:
        print(f"处理文件时出错：{str(e)}")
        sys.exit(1)


def save_failed_packages_to_excel(failed_packages_info):
    """
    将失败包信息保存到Excel文件
    
    Args:
        failed_packages_info (list): 包含失败包信息的字典列表
    """
    try:
        # 在函数内部导入pandas和datetime，减少不必要的全局依赖
        import pandas as pd
        from datetime import datetime
        
        # 创建DataFrame
        df = pd.DataFrame(failed_packages_info)
        
        # 生成带时间戳的文件名
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        excel_file = os.path.join(os.getcwd(), f'install_failed_packages_{timestamp}.xlsx')
        
        # 写入Excel文件
        df.to_excel(excel_file, index=False)
        
        print(f"\n已将失败包信息保存到：{excel_file}")
    except ImportError as e:
        print(f"导入依赖失败：{str(e)}")
        print("请确保已安装pandas和openpyxl：pip3 install pandas openpyxl")
    except Exception as e:
        print(f"保存失败包信息到Excel时出错：{str(e)}")


def main():
    """
    主函数
    """
    print("AGIROS包全量安装测试工具")
    print("=" * 50)
    
    # 步骤一：配置软件源
    print("\n步骤一：配置软件源")
    print("-" * 30)
    repo_content = """[agiros-loong-oemaker-packages]
name=agiros-loong-oemaker-packages
baseurl=https://eulermaker.compass-ci.openeuler.openatom.cn/api/ems1/repositories/AGIROS_2403_250627/openEuler%3A24.03-LTS/$basearch
enabled=1
gpgcheck=0

[oemaker-the-third-packages]
name=oemaker-the-third-packages
baseurl=https://eulermaker.compass-ci.openeuler.openatom.cn/api/ems1/repositories/the-third-packages/openEuler%3A24.03-LTS/$basearch
enabled=1
gpgcheck=0"""
    
    try:
        # 写入软件源配置文件
        with open('/etc/yum.repos.d/agiros.repo', 'w', encoding='utf-8') as f:
            f.write(repo_content)
        print("✓ 软件源配置文件创建成功")
        
        # 清除缓存并更新
        print("正在更新软件源缓存...")
        subprocess.run(['yum', 'clean', 'all'], capture_output=True, text=True, check=True)
        subprocess.run(['yum', 'makecache'], capture_output=True, text=True, check=True)
        print("✓ 软件源缓存更新成功")
    except Exception as e:
        print(f"✗ 配置软件源失败: {str(e)}")
        print("请检查是否有root权限")
    
    # 步骤二：安装python3-pip并安装必要的Python包
    print("\n步骤二：安装python依赖包")
    print("-" * 30)
    
    # 安装python3-pip
    try:
        print("正在安装python3-pip...")
        subprocess.run(['yum', 'install', '-y', 'python3-pip'], capture_output=True, text=True, check=True)
        print("✓ python3-pip安装成功")
        
        # 使用pip安装pandas和openpyxl
        print("正在安装pandas和openpyxl...")
        subprocess.run(['pip3', 'install', '--upgrade', 'pip'], capture_output=True, text=True)
        subprocess.run(['pip3', 'install', 'pandas', 'openpyxl'], capture_output=True, text=True)
        print("✓ pandas和openpyxl安装成功")
    except Exception as e:
        print(f"✗ 安装依赖包失败: {str(e)}")
    
    # 步骤三：获取AGIROS所有包名称并保存
    print("\n步骤三：获取AGIROS所有包名称")
    print("-" * 30)
    try:
        # 从指定repo获取所有包名
        print("正在从agiros-loong-oemaker-packages源获取所有包名...")
        # 使用yum list all命令，并指定repo，然后提取包名
        result = subprocess.run(
            ['yum', 'list', 'all', '--disablerepo=*', '--enablerepo=agiros-loong-oemaker-packages'],
            capture_output=True,
            text=True
        )
        
        if result.returncode == 0:
            # 提取包名
            package_names = []
            for line in result.stdout.split('\n'):
                # 跳过空行和表头
                if line.strip() and not line.startswith('已加载插件') and not line.startswith('可安装的软件包') and not line.startswith('\t'):
                    # 包名通常在每行的开头，以空格分隔
                    parts = line.split()
                    if parts and '.' in parts[0]:
                        # 提取包名（去掉版本信息部分）
                        pkg_name = parts[0].split('.')[0]
                        if pkg_name.startswith('agiros-loong-'):
                            package_names.append(pkg_name)
            
            # 去重
            package_names = list(set(package_names))
            # 剔除包含mrpt2字符串的包
            package_names = [pkg for pkg in package_names if 'mrpt2' not in pkg]
            package_names.sort()  # 排序以便于阅读
            
            # 保存到agiros.txt文件
            output_file = os.path.join(os.getcwd(), 'agiros.txt')
            with open(output_file, 'w', encoding='utf-8') as f:
                for pkg in package_names:
                    f.write(pkg + '\n')
            
            print(f"✓ 成功获取 {len(package_names)} 个AGIROS包名")
            print(f"✓ 已保存到文件：{output_file}")
        else:
            print(f"✗ 获取包名失败：{result.stderr}")
    except Exception as e:
        print(f"✗ 获取AGIROS包名时出错：{str(e)}")
    
    # 步骤四：全量安装测试
    print("\n步骤四：全量安装测试")
    print("-" * 30)
    # 获取当前目录下的agiros.txt文件
    file_path = os.path.join(os.getcwd(), 'agiros.txt')
    
    # 运行安装测试
    print("\n开始包安装测试...")
    install_packages_from_file(file_path)


if __name__ == "__main__":
    main()